﻿#include "MaterialOperationNodeView.h"


#include "MaterialGraph/Node/MaterialGraphNodeViewModel.h"
#include "MaterialOperationNodeViewModel.h"

#include "MaterialGraph/Pin/MaterialGraphPinViewModel.h"

#include "Widgets/TextWidget.h"
#include "Widgets/RectangleWidget.h"
#include "Widgets/ImageWidget.h"
#include "Widgets/EditorCheckBoxWidget.h"
#include "Widgets/Mouse/MouseWidget.h"
#include "Widgets/Keyboard/KeyboardWidget.h"

#include "Widgets/Positioners/HorizontalPositionerWidget.h"
#include "Widgets/Positioners/VerticalPositionerWidget.h"

#include "Framework/Editor.h"
#include "Theme/EditorTheme.h"

#include "Asset/EditorDefaultPackage.h"


void RMaterialOperationNodeView::BindViewModel(TSharedObjectPtr<RMaterialGraphNodeViewModel> InModel)
{
    Super::BindViewModel(InModel);

    OperationViewModel = InModel;
}

void RMaterialOperationNodeView::RegenerateContentWidget()
{
    Super::RegenerateContentWidget();

    auto OutputLine=CreateSimpleOutputPinWidget(RootWidget,RootWidget,0,1);

    //a combo box to select operation
    auto OperationLine=CreateLine(RootWidget,RootWidget,2);

    auto OperationLineBackground= NewWidget<RRectangleWidget>(OperationLine);
    OperationLineBackground->Anchor.VerticalFill(OperationLine);
    OperationLineBackground->Anchor.LeftReference=OperationLine;
    OperationLineBackground->Anchor.LeftOffset=OperationViewModel->LineHorizontalPadding;
    OperationLineBackground->Anchor.RightReference=OperationLine;
    OperationLineBackground->Anchor.RightOffset=OperationViewModel->LineHorizontalPadding;
    OperationLineBackground->FillColor= REditor::Get()->CurrentTheme->MaterialEditableBackground;
    OperationLineBackground->Radius=OperationViewModel->BackgroundRadius;

    auto OperationText=NewWidget<RTextWidget>(OperationLine);
    OperationText->Anchor.VerticalFill(OperationLine);
    OperationText->Anchor.LeftReference=OperationLineBackground;
    OperationText->Anchor.LeftOffset=OperationViewModel->LineHorizontalPadding;
    OperationText->Text=[this](){
        return OperationViewModel->GetOperationName();
    };
    OperationText->VerticalAlignment=ETextVerticalAlignment::Center;

    //this keyboard is just used to make popup menu auto hide
    auto PopupKeyboard=NewWidget<RKeyboardWidget>(OperationLine);
    RKeyboardWidgetWeakPtr WeakPopupKeyboard=PopupKeyboard;

    auto OperationMouse=NewWidget<RMouseWidget>(OperationLine);
    OperationMouse->Anchor.Fill(OperationLine);
    OperationMouse->AutoFocusTarget=PopupKeyboard;

    auto ComboBoxIcon=NewWidget<RImageWidget>(OperationLine);
    ComboBoxIcon->Anchor.RightReference=OperationLineBackground;
    ComboBoxIcon->Anchor.VerticalCenterReference=OperationLine;
    ComboBoxIcon->Width=20;
    ComboBoxIcon->Height=20;
    ComboBoxIcon->Image=
        REditorDefaultPackage::Get()->GetIcon(U"CodiconChevronDown");

    auto ComboBoxPopup=NewWidget<RWidget>(RootWidget);
    PopupKeyboard->Anchor.Fill(ComboBoxPopup);
    ComboBoxPopup->Height= OperationViewModel-> GetPopupMenuHeight();
    ComboBoxPopup->Width= OperationViewModel-> GetPopupMenuWidth();
    ComboBoxPopup->Anchor.BottomReference=OperationText;
    ComboBoxPopup->Anchor.BottomReferenceEdge=EVerticalWidgetEdge::Top;
    ComboBoxPopup->Anchor.LeftReference=OperationText;
    ComboBoxPopup->Visible=[WeakPopupKeyboard](){
        return WeakPopupKeyboard->IsFocused();
    };

    auto PopupBackground=NewWidget<RRectangleWidget>(ComboBoxPopup);
    PopupBackground->Anchor.Fill(ComboBoxPopup);
    PopupBackground->FillColor= REditor::Get()->CurrentTheme->BackgroundColor;
    PopupBackground->Radius=4;

    auto HorizontalLayout=NewWidget<RHorizontalPositionerWidget>(ComboBoxPopup);
    HorizontalLayout->Anchor.TopReference=ComboBoxPopup;
    HorizontalLayout->Anchor.TopOffset= OperationViewModel->PopupMenuPadding;
    HorizontalLayout->Anchor.LeftReference=ComboBoxPopup;
    HorizontalLayout->Anchor.LeftOffset= OperationViewModel->PopupMenuPadding;
    HorizontalLayout->Anchor.RightReference=ComboBoxPopup;
    HorizontalLayout->Anchor.RightOffset= OperationViewModel->PopupMenuPadding;
    HorizontalLayout->Anchor.BottomReference=ComboBoxPopup;
    HorizontalLayout->Anchor.BottomOffset= OperationViewModel->PopupMenuPadding;
    HorizontalLayout->Spacing= OperationViewModel->PopupMenuHorizontalSpacing;

    for(int64_t ColumnIndex=0;
        ColumnIndex<OperationViewModel->GetPopupMenuColumnNum();
        ++ColumnIndex)
    {
        auto Column=NewWidget<RVerticalPositionerWidget>(HorizontalLayout);
        Column->Width= OperationViewModel-> GetPopupMenuColumnWidth(ColumnIndex);
        Column->Spacing= OperationViewModel->PopupMenuVerticalSpacing;
    
        auto ColumnText=NewWidget<RTextWidget>(Column);
        ColumnText->Text= OperationViewModel-> GetPopupMenuColumnName(ColumnIndex);
        ColumnText->Anchor.HorizontalFill(Column);
        ColumnText->VerticalAlignment=ETextVerticalAlignment::Center;
        ColumnText->Height= OperationViewModel-> ColumnLineHeight;
        ColumnText->Color= REditor::Get()->CurrentTheme->UninteractableTextColor;

        for(int64_t LineIndex=0;
            LineIndex<OperationViewModel->GetPopupMenuLineNum(ColumnIndex);
            ++LineIndex)
        {
            auto Line=NewWidget<RWidget>(Column);
            Line->Anchor.HorizontalFill(Column);
            Line->Height= OperationViewModel-> ColumnLineHeight;

            auto LineMouse=NewWidget<RMouseWidget>(Line);
            LineMouse->Anchor.Fill(Line);
            LineMouse->OnClicked.BindLambda([this,ColumnIndex,LineIndex,WeakPopupKeyboard](const SMouseButtonEvent&){
                OperationViewModel->UseOperationTypeInMenu(ColumnIndex,LineIndex);
                WeakPopupKeyboard->Unfocus();
                return true;
            });
            RMouseWidgetWeakPtr WeakLineMouse=LineMouse;

            auto LineHighlight=NewWidget<RRectangleWidget>(Line);
            LineHighlight->Anchor.Fill(Line);
            LineHighlight->Radius=4;
            LineHighlight->FillColor= REditor::Get()->CurrentTheme->HighlightColor;
            LineHighlight->Visible=[WeakLineMouse](){
                return WeakLineMouse->IsHovered();
            };

            auto LineText=NewWidget<RTextWidget>(Line);
            LineText->Text= OperationViewModel-> GetPopupMenuItemName(ColumnIndex,LineIndex);
            LineText->Anchor.Fill(Line);
            LineText->VerticalAlignment=ETextVerticalAlignment::Center;
        }
    }

    
    auto EnableClampLine=CreateCheckBoxWidget(
        RootWidget
        ,RootWidget
        ,3
        ,[this](){
            return OperationViewModel->IsClampEnable();
        }
        ,CString(U"限制到[0,1](clamp)")
        ,[this](bool InIsChecked){
            OperationViewModel->EnableClamp(InIsChecked);
        }
    );

    auto InputPinA=CreateVector1DInputPinWidgetWithoutLimit(RootWidget,RootWidget,0,4);
    auto InputPinB=CreateVector1DInputPinWidgetWithoutLimit(RootWidget,RootWidget,1,5);
    InputPinB->Visible=[this](){
        return OperationViewModel->IsInputBVisible();
    };
    auto InputPinC=CreateVector1DInputPinWidgetWithoutLimit(RootWidget,RootWidget,2,6);
    InputPinC->Visible=[this](){
        return OperationViewModel->IsInputCVisible();
    };
}